﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;

namespace конфигуратор
{
    public class Поле : INotifyPropertyChanged
    {
        public  ДинамикОбъект ДинОбъект;
        public FieldInfo F { get; set;}
        public int НомерНаследника { get; set; }
        public string ИмяТипаОпределившегоПоле { get { return F.DeclaringType.ИмяТипа(); } }
        public string ТипПоля { get { return F.FieldType.ИмяТипа(); } }
        public string ИмяПоля { get { return F.Name; } }
        
        public object Значение
        {
            get
            {
                try
                {
                    return F.GetValue( ДинОбъект.Объект );
                }
                catch ( Exception )
                {
                    return null;
                }
            }
            set
            {
                try
                {
                    object значение;
                    if ( value is string )
                    {
                        var тип = ДинОбъект.Объект == null ? F.FieldType : F.GetValue( ДинОбъект.Объект );

                        значение = Парсер.Преобразовать((string) value, тип.GetType());
                    }
                    else  
                    {
                        значение = value;
                    }
                    
                    F.SetValue( ДинОбъект.Объект, значение );

                    ДинОбъект.ВызватьМетод( "OnPropertyChanged",  ""  );
                }
                catch
                {
                }
                   ДинОбъект.Обновить();
            }
        }
        public override string ToString ()
        {
            return F.Name + " : " + Значение;
        }        
        public string[]  СписокПеречислителя
        {
            get
            {
                if (!F.FieldType.IsEnum) return null;
                return Enum.GetNames( F.FieldType);
            }
        }

        public static List<Поле> ДатьСписокПолей ( ДинамикОбъект динОбъект )
        {
           
            if ( динОбъект == null || динОбъект.Тип ==null ) return null;
             var списокПолей = new List<Поле>();

             var предки = динОбъект.ОписаниеТипа.Предки.ToList();
             предки.Insert( 0, динОбъект.Тип );

             for ( int номер = 0; номер < предки.Count; номер++ )
             {
                 var массив = предки[номер].GetFields( BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly );
                 foreach ( var поле in массив )
                 {
                     списокПолей.Add( new Поле() { ДинОбъект = динОбъект, F = поле, НомерНаследника = номер } );
                 }

             }

            return списокПолей;
        }
    
        public string АтрибутыДоступа
        {
            get
            {  
                if ( F.IsPrivate ) return "private";      
                if ( F.IsPublic ) return "public";
                if ( F.IsFamilyOrAssembly ) return "protected internal";
                if ( F.IsAssembly ) return "internal";
                if ( F.IsFamily) return "protected";
                return "";
              }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void Обновить()
        {
            if ( PropertyChanged != null )
                PropertyChanged( this, new PropertyChangedEventArgs( "" ) );
        }
    }
}
